Web 上の Raw 画像は正しい原点と色を使用しています
まとめ
Web 上での RAW 画像のレンダリング方法が修正されました
他のプラットフォームのものと一致するようになりました。
これにより、誤ったデータをフィードする必要があった従来のアプリが壊れます
にui.ImageDescriptor.raw
またui.decodeImageFromPixels
、
結果として得られる画像が上下逆さまになってしまう
そして間違った色で
(赤と青のチャンネルが交換されます。)
コンテクスト
Flutterが内部的に使用する「ピクセルストリーム」
は常に同じ形式として定義されています。
ピクセルごとに、4 つの 8 ビット チャネルが定義された順序でパックされます。
によってformat
引数を一行にグループ化し、
左から右に、次に上から下の行に進みます。
ただし、Flutter for Web、より具体的には HTML レンダラは、
間違った方法で実装されていた
BMP 形式の仕様についての誤った理解が原因です。
その結果、アプリまたはライブラリがui.ImageDescriptor.raw
またui.decodeImageFromPixels
、
ピクセルを下から上に送り、赤と青のチャンネルを交換する必要がありました。
(たとえば、ui.PixelFormat.rgba8888
フォーマット、
データの最初の 4 バイトは青、緑、
代わりに、最初のピクセルの赤とアルファ チャネルが使用されます。)
このバグは次の方法で修正されましたエンジン#29593、 ただし、アプリとライブラリはデータの生成方法を修正する必要があります。
変更内容の説明
のpixels
の議論ui.ImageDescriptor.raw
またui.decodeImageFromPixels
で記述された正しいピクセル順序が使用されるようになりました。format
、
左上隅から始まります。
これら 2 つの関数を直接呼び出してレンダリングされた画像 これらの関数を直接呼び出す従来のコードは、 画像が逆さまで色が間違っているのを見つけます。
移行ガイド
アプリが最新バージョンの Flutter を使用していてこの状況が発生した場合、 最も直接的な解決策は、画像を手動で反転し、代替手段を使用することです。 ピクセル形式。ただし、これが最も最適化されたソリューションである可能性は低く、 このようなピクセル データは通常、他のソースから構築されるため、 構築プロセス中に反転できるようになります。
移行前のコード:
import 'dart:typed_data';
import 'dart:ui' as ui;
// Parse `image` as a displayable image.
//
// Each byte in `image` is a pixel channel, in the order of blue, green, red,
// and alpha, starting from the bottom left corner and going row first.
Future<ui.Image> parseMyImage(Uint8List image, int width, int height) async {
final ui.ImageDescriptor descriptor = ui.ImageDescriptor.raw(
await ui.ImmutableBuffer.fromUint8List(image),
width: width,
height: height,
pixelFormat: ui.PixelFormat.rgba8888,
);
return (await (await descriptor.instantiateCodec()).getNextFrame()).image;
}
移行後のコード:
import 'dart:typed_data';
import 'dart:ui' as ui;
Uint8List verticallyFlipImage(Uint8List sourceBytes, int width, int height) {
final Uint32List source = Uint32List.sublistView(ByteData.sublistView(sourceBytes));
final Uint32List result = Uint32List(source.length);
int sourceOffset = 0;
int resultOffset = 0;
for (final int row = height - 1; row >= 0; row -= 1) {
sourceOffset = width * row;
for (final int col = 0; col < width; col += 1) {
result[resultOffset] = source[sourceOffset];
resultOffset += 1;
sourceOffset += 1;
}
}
return Uint8List.sublistView(ByteData.sublistView(sourceBytes))
}
Future<ui.Image> parseMyImage(Uint8List image, int width, int height) async {
final Uint8List correctedImage = verticallyFlipImage(image, width, height);
final ui.ImageDescriptor descriptor = ui.ImageDescriptor.raw(
await ui.ImmutableBuffer.fromUint8List(correctedImage),
width: width,
height: height,
pixelFormat: ui.PixelFormat.rgba8888,
);
return (await (await descriptor.instantiateCodec()).getNextFrame()).image;
}
さらに厄介な状況は、ライブラリを作成しているときです。 そして、このライブラリを最新の Flutter の両方で動作させたいとします。 そしてパッチ前のものも。 その場合、動作が変更されたかどうかを判断できます 最初に単一ピクセルをデコードさせることによって。
移行後のコード:
Uint8List verticallyFlipImage(Uint8List sourceBytes, int width, int height) {
// Same as the example above.
}
late Future<bool> imageRawUsesCorrectBehavior = (() async {
final ui.ImageDescriptor descriptor = ui.ImageDescriptor.raw(
await ui.ImmutableBuffer.fromUint8List(Uint8List.fromList(<int>[0xED, 0, 0, 0xFF])),
width: 1, height: 1, pixelFormat: ui.PixelFormat.rgba8888);
final ui.Image image = (await (await descriptor.instantiateCodec()).getNextFrame()).image;
final Uint8List resultPixels = Uint8List.sublistView(
(await image.toByteData(format: ui.ImageByteFormat.rawStraightRgba))!);
return resultPixels[0] == 0xED;
})();
Future<ui.Image> parseMyImage(Uint8List image, int width, int height) async {
final Uint8List correctedImage = (await imageRawUsesCorrectBehavior) ?
verticallyFlipImage(image, width, height) : image;
final ui.ImageDescriptor descriptor = ui.ImageDescriptor.raw(
await ui.ImmutableBuffer.fromUint8List(correctedImage), // Use the corrected image
width: width,
height: height,
pixelFormat: ui.PixelFormat.bgra8888, // Use the alternate format
);
return (await (await descriptor.instantiateCodec()).getNextFrame()).image;
}
タイムライン
リリースされたバージョン: 2.9.0-0.0.pre
安定版リリース: 2.10
参考文献
API ドキュメント:
decodeImageFromPixels
ImageDescriptor.raw
関連する問題:
- Web: マスターの回帰 - BMP エンコーダーの変更により PDF 表示が歪む
- Web: ImageDescriptor.raw は画像を反転および反転します (部分的な理由を含む)
関連する PR:
- Web: Reland: BMP エンコーダを修正
- ImageDescriptor.raw のピクセル順序を明確にし、バージョン検出器を追加します